# -*- coding: utf-8 
from EssaiAVA.ava.models import *
from EssaiAVA.ava.outils.restaurant import *
from EssaiAVA.ava.outils.geocode import *
from EssaiAVA.ava.outils.message import *


def Optimisation_Restaurant(invit):
    tous_invites = invit.invite_set.all()
    invites= []
    #tableau des invités présents
    for i in range(0, len(tous_invites)):
        if tous_invites[i].presence==True:
            invites.append(tous_invites[i])
    tab = []
    # tableau des coordonnées de chaque invité présent
    for i in range(0, len(invites)):
        tab.append([invites[i].coord.latitude, invites[i].coord.longitude])
    G = barycentre(tab)
    coord_bary = Coordonnees(longitude=G[1], latitude=G[0])
    coord_bary.save()
    invit.coord_barycentre=coord_bary
    invit.save()
    dico = get_restaurants(G[0], G[1])
    # on construit la liste des restau candidats
    list_restau = []
    for restaurant in dico:
        R = info_restaurant(restaurant)
        coord_restau = Coordonnees(longitude=R[1], latitude=R[0])
        coord_restau.save()
        url = get_details(R[3])
        type = get_type(url)
        dist = distance(coord_restau.latitude, coord_restau.longitude, invit.coord_barycentre.latitude, invit.coord_barycentre.longitude)
        print type
        print get_type_number(type)
        r = Restaurant(nom=R[2], coord=coord_restau, invit=invit, url=url, type=get_type_number(type), dist=dist)
        r.save()
        list_restau.append(r)
    #on construit la liste des voix
    list_voix = []
    for un_invite in invites:
        list_notes = [2, 2, 2, 2, 2]
        list_crit = un_invite.critere_set.all()
        for crit in list_crit:
            if crit.type=='GO':
                index = convert_type_to_int(crit.detail_set.all()[0].detail)
                list_notes[index]=crit.nbre_etoile
        list_voix.append(classement(list_notes))
    rep = tri(list_restau, list_voix)
    index_min = rep[0]
    for i in rep:
        if i<index_min:
            index_min=i
    restau_choisi = list_restau[rep.index(index_min)]
    restau_choisi.choisi = True
    restau_choisi.save()
    envoyer_message_resultat(invit)
    print "Fini"
    
    

def matrvid(x):
    # permet de créer une matrice nulle
    M = []
    for i in range(x):
        ll = []
        for j in range(x):
            ll.append(0)
        M.append(ll)
    return M


def matr2sum (a, b):
    #permet de sommer deux matrices
    M = matrvid(len(a))
    for i in range(len(a)):
        for j in range(len(a[i])):
            M[i][j] = a[i][j] + b[i][j]
    return M

def Mvoixtype(list_restau, classement):
    M = matrvid(len(list_restau))
    l = []
    for i in range(len(classement)):
        q = []
        for n in range(len(classement)):
            if classement[n] == (i+1):
                q.append(n+1)
        l.append(q)
    s=0
    for i in range(len(l)):
        k = -1
        for j in range(len(l[i])):
            for r in range(len(list_restau)):
                if list_restau[r].type == l[i][j]:
                    M[r][i+s] = M[r][i+s]+1
                    k = k + 1
        s = s+k
     
    return M

def tritype(list_restau, list_voix):
    M = matrvid(len(list_restau))
    for v in list_voix:
        M = matr2sum (M, Mvoixtype(list_restau, v))
    return M

def tridistance(list_restau):
    M = matrvid(len(list_restau))
    l = []
    for i in range(len(list_restau)):
        l.append(list_restau[i].dist)
    l.sort()

    lr = []
    t = -1
    for i in range(len(l)):
        if l[i] != t:
            t = l[i]
            lr.append(t)       
    s=0
    for i in range(len(lr)):
        k = -1
        for r in range(len(list_restau)):
            if list_restau[r].dist == lr[i]:
                M[r][i+s] = M[r][i+s]+1
                k = k + 1
        s = s+k
    return M


def tri (list_restau, list_voix):
    # a partir d'une liste de restaurants candidats et de la liste des classements des gouts de chaque utilisateur
    # rend une liste correspondant au classement de chaque restaurant, 0 etant le meilleur choix
    M = matrvid(len(list_restau))
    M = matr2sum (M, tritype (list_restau, list_voix))
    M = matr2sum (M, tridistance (list_restau))
    l=[]
    for i in range(len(list_restau)):
        a = 0
        for j in range(len(list_restau)):
            a = a + M[i][j]*j
        l.append(a)
    lc = []
    for i in range(len(l)):
        lc.append(l[i])
    lc.sort()
    lr = []
    t = -1
    for i in range(len(lc)):
        if lc[i] != t:
            t = lc[i]
            lr.append(t)
    s=0
    for i in range(len(lr)):
        k = -1
        for r in range(len(list_restau)):
            if l[r] == lr[i]:
                k = k + 1
        s = s+k
    return l

def classement(list_notes):
    #prend une liste de notes et rend une liste de classement des gouts
    list_recopie = []
    for note in list_notes:
        list_recopie.append(note)
    list_notes.sort()
    list_notes.reverse()
    list_classement = [0, 0, 0, 0, 0]
    classement = 1
    while len(list_notes)>0:
        note = list_notes[0]
        for i in range(len(list_recopie)):
            if list_recopie[i]==note:
                list_classement[i]=classement
                list_notes.remove(note)
        classement+=1
    return list_classement
        